/**
 * 
 */
package cz.cuni.mff.abacs.burglar.logics.planning.instructions;



/**
 * 
 * 
 * Immutable class.
 * 
 * <ul>
 * <li>MOVE: agent, subject</li>
 * <li>OPEN: agent, subject</li>
 * <li>CLOSE: agent, subject</li>
 * </ul>
 * 
 * @author abacs
 *
 */
public class Instruction {
	
	
	/**  */
	public static enum code {
		UNDEFINED,
		// atomic instructions:
		MOVE,
		OPEN,      CLOSE,
		UNLOCK,    LOCK,
		PICK_UP,
		
		// complex instructions:
		COMPLEX_MOVE,
		ENTER_DOOR,
	};
	
	/**  */
	public final code _code;
	
	/**  */
	public final int _agentId;
	
	/**  */
	public final int _subjectId;
	
	/**  */
	public final int _itemId;
	
	
	// -------------------------------------------------------------------------
	
	
	/** 
	 * Should be used to create move, open, close commands.
	 * 
	 * @param code
	 * @param agentId
	 * @param subjectId
	 *  */
	public Instruction(code code, int agentId, int subjectId) {
		this._code = code;
		this._agentId = agentId;
		this._subjectId = subjectId;
		this._itemId = -1;
	}
	
	
	/**
	 * Should be used to create lock, unlock commands.
	 * 
	 * @param code
	 * @param agentId
	 * @param subjectId
	 * @param itemId
	 *  */
	public Instruction(
			code code,
			int agentId,
			int subjectId,
			int itemId
	) {
		this._code = code;
		this._agentId = agentId;
		this._subjectId = subjectId;
		this._itemId = itemId;
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Whether it should be extended before execution.
	 * 
	 * @return
	 */
	public boolean isComplexInstruction() {
		if(this._code == code.COMPLEX_MOVE || this._code == code.ENTER_DOOR)
			return true;
		return false;
	}
	
	
	/**
	 * 
	 * @param other
	 * @return
	 */
	public boolean matches(Instruction other) {
		return	this._agentId == other._agentId && 
				this._code == other._code &&
				this._itemId == other._itemId &&
				this._subjectId == other._subjectId;
	}
	
	
}
